﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Threading;

using ABCat.Core.Plugins;
using ABCat.Core.Plugins.Catalog.FilteringLogics;
using ABCat.Core.Plugins.DataProviders;
using ABCat.Core.Plugins.UI;
using ABCat.Shared;
using ABCat.Shared.Properties;

using NLog;

namespace ABCat.Core
{
	public sealed class Context : INotifyPropertyChanged
	{
		#region + Events +

		public event PropertyChangedEventHandler PropertyChanged;

		#endregion
		#region + Fields +

		public const string AuthorDefaultName = "<Не задано>";
		public const string GenreDefaultName = "<Не задано>";

		public readonly Dispatcher UiDispatcher;

		private readonly PluginCreatorAttribute _dbPluginCreatorAttribute;
		private readonly Logger _logger;
		private readonly PluginsFactory _pluginsFactory;
		private readonly Action<Context, Config> _showConfigWindowAction;
		private readonly Func<LoginInfo,LoginInfo> _showLoginWindowAction;

		#endregion
		#region + Properties +

		public Logger Logger
		{
			get { return _logger; }
		}

		public PluginsFactory PluginsFactory
		{
			get
			{
				return _pluginsFactory;
			}
		}

		#endregion
		#region + Ctor +

		public Context([NotNull] Logger logger, [NotNull] Action<Context, Config> showConfigWindowAction, [NotNull] Func<LoginInfo,LoginInfo> showLoginWindowAction)
		{
			UiDispatcher = Application.Current.Dispatcher;
			_logger = logger;
			_showConfigWindowAction = showConfigWindowAction;
			_showLoginWindowAction = showLoginWindowAction;
			_pluginsFactory = new PluginsFactory(this, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plug-ins"));
			_pluginsFactory.LiveInstancesChanged += _pluginsFactory_LiveInstancesChanged;
			_dbPluginCreatorAttribute = _pluginsFactory.GetPlugins<IDbContainer>().First();
		}

		#endregion
		#region + Logic +

		public IDbContainer CreateDbContainer(bool autoSave)
		{
			var result = _dbPluginCreatorAttribute.CreateInstance<IDbContainer>(this);
			result.AutoSaveChanges = autoSave;
			return result;
		}

		public void ShowConfigWindow(Config targetConfig)
		{
			_showConfigWindowAction(this, targetConfig);
		}

		public LoginInfo ShowLoginWindow(LoginInfo loginInfo)
		{
			return _showLoginWindowAction(loginInfo);
		}

		[NotifyPropertyChangedInvocator]
		private void OnPropertyChanged([CallerMemberName] string propertyName = null)
		{
			PropertyChangedEventHandler handler = PropertyChanged;
			if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
		}

		private void _pluginsFactory_LiveInstancesChanged(object sender, EventArgs e)
		{
			OnPropertyChanged("Plugins");
		}

		#endregion
	}
}